home *** CD-ROM | disk | FTP | other *** search
/ Super Audio / Super Audio.iso / replay / _armovie / documents / codecif < prev    next >
Text File  |  1997-11-10  |  26KB  |  552 lines

  1.             The video codec interfaces for Acorn Replay
  2.             ===========================================
  3.  
  4. Introduction
  5. ------------
  6.  
  7. The Replay "ARMovie" format allows for different sound and video compression
  8. formats. Interfaces inside the ARMovie Player program ("!ARMovie.Player")
  9. allow introduction of new video decompression code, an appropriate
  10. compression program and allow other programs to use the ARMovie video
  11. decompressors. Sound format 2 provides similar independence for sound
  12. compression methods: the format directly names the sound decompression code
  13. which will be used - provided this is located in <ARMovie$SoundDir> (see
  14. ToUseSound for more details).
  15.  
  16. There are two ways to introduce new video compression formats: total
  17. replacement of the Player program (provide a !ARMovie.Decomp<N>.!RunImage
  18. for a new compression type <N> which implements the entire ProgIf command
  19. interface) or provide a decompressor which uses the Player interface
  20. (provide a !ARMovie.Decomp<N>.Decompress file). A batch compression
  21. interface is defined for compression programs which are named
  22. !ARMovie.Decomp<N>.BatchComp and will be called automatically by !AREncode
  23. (and, presumably, other utilities).
  24.  
  25. Total replacement decompression interface
  26. =========================================
  27.  
  28. When a Replay ARMovie file is to be played, the resource !ARMovie.Player
  29. gets called with a command string by the operating system. Player would
  30. normally use the software decompression interface and paint the movie on the
  31. screen itself, but it can also relinquish the entire task (e.g. for a format
  32. which is decompressed by hardware and video overlayed onto the screen) if
  33. that is required. After a minimal check that the ARMovie file is valid,
  34. !ARMovie.Player reads the video format number and checks the appropriate
  35. Decomp directory for the existence of a '!RunImage' file. If this exists,
  36. Player will run it with the ARMovie file and other arguments (many of them
  37. are in ARMovie$ExtraArgs) which were passed to Player.
  38.  
  39. The replacement routine should obey as much of the command set of Player as
  40. possible (though -shape may be asking too much in the above example!). The
  41. replacement program is free to get its data from anywhere, but it is
  42. recommended that ARMovie files are present with standard headers in order
  43. that general multimedia programs will see something they understand.
  44.  
  45. Video decompression interface
  46. =============================
  47.  
  48. The total replacement of !ARMovie.Player is a very large task; it is much
  49. easier to provide a new video decompressor only and rely on the
  50. !ARMovie.Player program doing the rest of the work. Acorn currently provide
  51. 10 video decompressors using this interface and many of them are provided
  52. with source.
  53.  
  54. Using this interface means keeping most of the architecture of the Player
  55. system:
  56.  
  57. - interleaved video+sound chunk format
  58. - format of sound code and interface to it
  59. - key frame system (but it can be ignored completely, also)
  60. - decompressor called in IRQ mode; should run with interrupts (mostly)
  61.   enabled
  62. - flags between disc loader and decompressor
  63. - flags between decompressor and screen painter
  64. - decompressor provides the colour looked up output
  65.  
  66. Details of using the sound system are in 'ToUseSound': either the current
  67. Acorn Replay sound code can be used or new sound formats added by sound code
  68. implementing the current interface (described from the point of view of the
  69. client in ToUseSound) can be added using format 2 to name the sound code. No
  70. changes to Player programs is required.
  71.  
  72. In order to start some of the decompressors (MovingLines, for example) at
  73. any position, the use of key frames is possible. The compressor stores the
  74. state of the stream at the start of each chunk, uncompressed, in the key
  75. frame data structure. The Player program will load the uncompressed file
  76. from the data structure in order to start decompression at an arbitrary
  77. point, providing the 'previous frame' state (see below). Decompressors which
  78. can start anywhere use an ARMovie file without the key frame data structure
  79. (by giving a -1 offset to the keys in the header).
  80.  
  81. The decompressor is called in IRQ mode with interrupts enabled in order to
  82. decompress the next frame. Code in the Player handles semaphores between
  83. decompression and painting frames and between loading the video chunks and
  84. decompressing frames. Other code in the Player takes data from the
  85. decompressed frames buffer and paints it onto the screen (in IRQ mode also)
  86. and code waits for compressed data buffers to be empty and refills them from
  87. the filing system (in User mode as the foreground task). To allow these
  88. other tasks to run, the IRQ code must leave interrupts enabled for as much
  89. time as possible (the MovingLines decompressor leaves interrupts enabled for
  90. all of its work). In any case IRQ must not be disabled for longer than 1
  91. full sound buffer: about 2mS.
  92.  
  93. The disc loader works in a double buffered manner: two buffers each
  94. containing either one or two chunks of data (2 or 4 seconds per buffer
  95. conventionally). The addresses of the two buffers and one or two chunks per
  96. buffer are all chosen dynamically and the Player program knows from the
  97. ARMovie header how many times to call the decompression code. The two
  98. buffers will always start on word addresses.
  99.  
  100. Using the interface play with existing Decompress code
  101. ------------------------------------------------------
  102.  
  103. As well as being able to provide new compression formats by using the
  104. Player/ Decompress interface, other programs can also use the Decompress
  105. code, in effect pretending to be the Player program as far as the Decompress
  106. code is concerned. This greatly extends the capability of the Replay system:
  107. programs could be written to play ARMovie files in the desktop while
  108. multitasking (obviously non-real time). Or sections of an ARMovie file could
  109. be decompressed to memory and edited. Or... The ability to patch the
  110. Decompress code allows player programs to load two copies of a Decompress
  111. code: patch one to generate data for one format and patch the other to
  112. generate data for a different format (e.g. non-dithered for the screen).
  113.  
  114. Such a playing program has to do all the tasks normally done by the
  115. !ARMovie.Player program:
  116.  
  117. - read the file header to discover the data
  118. - establish the dither for the screen if needed
  119. - load the right decompress code, patch and initialise it
  120. - load the key frame if required
  121. - load the chunks from the file
  122. - call the decompress entry point for each frame in the block
  123.  
  124. but it need do no more than this. It can structure its data structures as it
  125. wishes (excepting that Decompress codes write pixels as words).
  126.  
  127. The Acorn provided BatchComp programs use ARMovie files as input and use the
  128. Decompress code in order to convert the data into a form they understand
  129. (indeed, they will use Decompress code even if the !RunImage total takeover
  130. exists) and thus get total isolation from the video compression method of
  131. the input ARMovie file.
  132.  
  133. Decompress "Info" file
  134. ----------------------
  135.  
  136. In order that Decompress code providers can incorporate their own names for
  137. formats, provide format origination text, provide compress and edit routines
  138. with hints on various formats, an Info file called Decomp<N>.Info can be
  139. provided (the !ARMovie.Player does not need this file). It contains the
  140. following information:
  141.  
  142. Name of format
  143. Originator
  144. exact number of bits per pixel (or empty if this is variable)
  145. desired x multiple; minimum x size; maximum x size
  146. desired y multiple; minimum y size; maximum y size
  147. temporal (or empty if temporal information is not required)
  148. list of colour spaces which can be held in the format
  149.  
  150. For example:
  151.  
  152. Moving Lines
  153. © Acorn Computers 1993
  154.  
  155. 1;1;1280
  156. 1;1;1024
  157. Temporal
  158. YUV 5,5,5; RGB 5,5,5
  159.  
  160. The colour space information allows programs like !AREncode to present the
  161. user with valid options.
  162.  
  163. Formal interface: "Decompress" file (any file type can be used)
  164. ---------------------------------------------------------------
  165.  
  166. The Player program loads the decompress code at a quad word aligned address
  167. in memory. It then processes the patch table and then calls the init point.
  168. Later on the player calls the decompressor in USR mode to decompress the
  169. first chunk's worth of frames (or to do -explode). For a full play, the
  170. player will call the decompressor in IRQ mode.
  171.  
  172. First word: patch table offset
  173. (32 bit word at byte offset 0)
  174.  
  175.  Purpose: to allow the player to insert pixel colour lookup in the
  176.           decompressor. May in future allow other values to patched.
  177.           Note that an unpatched decompressor should still work!!
  178.  
  179.  The offset table consists of words. Each word has the bottom 16 bits as the
  180.  byte offset of a word (usually an instruction) from the start of the
  181.  decompressor. The top 4 bits are an opcode number. The remaining 12
  182.  bits may have a meaning for that opcode. The list is terminated by a
  183.  word of -1.
  184.  
  185.  Opcode 0: patch in colour lookup
  186.   bits 27..24: destination register
  187.   bits 23..20: source register
  188.   bits 19..17: pixel lookup table register
  189.  The Player alters the word to lookup the pixel colour. The value of
  190.  the source register and the size of the result in the destination
  191.  register may change for different decompressors. For MovingLines the
  192.  source register value is either RGB or YUV 15 bits and the destination
  193.  value is always a word value. An unpatched MovingLines decompressor
  194.  produces RGB or YUV output.
  195.  
  196. Second word: init entry point
  197. (byte offset 4)
  198.  
  199.  Purpose: to allow the decompressor to initialise any tables or other
  200.           values that are needed. These will be inside the Decompress
  201.           code space or allocated by the init routine.
  202.  
  203.  On entry:
  204.    r0 - source x size of movie
  205.    r1 - source y size of movie
  206.    r2..r12 - undefined: scratch
  207.    r13 - stack
  208.    r14 - return address
  209.    processor mode: USR
  210.  On exit
  211.    r0-r12 may be corrupted
  212.    r13 - same as on entry
  213.    flags - V set signals error: r0 points to an error block
  214.  
  215. Third word: decompress entry point
  216.  
  217.  Purpose: decompress precisely one frame
  218.  
  219.  On entry:
  220.    r0 to r5 are set up by Player as follows:
  221.    r0 - source byte pointer
  222.    r1 - output pointer - save output pixels here (word aligned)
  223.    r2 - previous output pointer (allows copying from previous frame)
  224.    r3 - pixel dither lookup table
  225.    r4 - return address (can't be r14...)
  226.    r5..r12 - scratch
  227.    r13 - small stack (RISC OS irq stack)
  228.    r14 - unuseable
  229.    processor mode: IRQ, interrupts ENABLED (usually)
  230.    flags - irrelevant
  231.  On exit
  232.    r0 - next value of source byte pointer
  233.    r1..r12 - irrelevant
  234.    r13 - must be same value as on entry
  235.    r14 - irrelevant
  236.    processor mode: IRQ, interrupts ENABLED
  237.    flags - irrelevant
  238.  
  239.  Decompressed pixels are stored as Words!!! For the MovingLines decompressor
  240.  to work, the source pointer (r0) must be half word aligned.
  241.  
  242. The 'DecompresH' file
  243. ---------------------
  244.  
  245. A decompression provider can additionally provide a DecompresH program. This
  246. has exactly the same interface as the Decompress file, but stores output
  247. pixels as half words. This allows the Player program to use less store (and
  248. run slightly faster) in some screen modes (in particular, mode 15).
  249.  
  250. Programs which use the decompression programs must not assume the existence
  251. of 'DecompresH' forms of decompressors and must be capable of using the
  252. 'Decompress' file instead. For some compression formats, the gain in the
  253. Player of using the half word output may be completely lost by inefficiency
  254. in the decompressor.
  255.  
  256. The 'Decom24' file
  257. -------------------
  258.  
  259. The 15 bit per pixel format allows fast colour lookup, but may not allow an
  260. accurate representation of a colour. The 'Decom24' file has an identical
  261. structure to the 'Decompress' file, but writes output colours as 24bpp
  262. values (in words) in the original colour space (i.e. the colour space
  263. conversion by table does not exist). Note that it is perfectly possible to
  264. have a file with 24bpp values used in the video stream where the original
  265. ARMovie file header still claims 16bpp, provided a 'Decompress' file is
  266. also present (for example, see Decomp8).
  267.  
  268. The 'Decom24xxx' files
  269. -------------------------------------
  270.  
  271. These files have the same interfaces as 'Decom24', but write their output
  272. in the 24bpp RGB colour space. A three character suffix represents which
  273. colour space the source comes from - e.g. 'Decom24YUV' or 'Decom24YIQ' -
  274. and this suffix should also be present in the ARMovie header at the end of
  275. the bits per pixel line. Note that no suffix is possible, defaulting back
  276. to 'Decom24' which provides no colour space translation (and so had better
  277. imply an RGB colour space source!).
  278.  
  279. NOTE: Decom24xxx writers - the target colour space is 8 bit R G B with each
  280. value in the range 0..255 (off..on), assumed gamma corrected (i.e. they will
  281. be presented directly to DACs and then to the CRT with no extra
  282. correction/changes).
  283.  
  284. The Batch Compression interface
  285. ===============================
  286.  
  287. A program 'BatchComp' can be provided in the Decomp<N> directory. The
  288. program should obey the compression parameters given below and take an
  289. ARMovie file as source (for example, by using the Decompress interface) and
  290. compress it to produce some of the basic building blocks of an ARMovie file
  291. which will later be turned into a final ARMovie file using 'Join' [aside:
  292. the mechanics of produce a multitrack ARMovie file are sufficiently complex
  293. that it is best to have all the capability in one program]. BatchComp should
  294. read a provided ARMovie Header file in order to work out what to do: it
  295. can use the header file to determine the number of frames per second, the
  296. number of frames per chunk and the volume of the sound data per chunk. It is
  297. then able to calculate (based on the supplied latency and bandwidth of the
  298. target decompression device) how many bytes it can allocate to each frame of
  299. video data. Larger numbers of frames per chunk mean more tolerance of device
  300. latency, but larger chunks mean the movie takes more memory to decompress
  301. and takes longer to start playing (since it has to read the first chunk).
  302. Headers should be set up for 2 second chunks by default.
  303.  
  304. CAUTION: BatchComp programs may only manage simple resampling to generate
  305. movies at different frame rates from the source. For example,
  306. MovingLine.BatchComp can make a 12.5 fps movie from a 25 fps source (or a 30
  307. fps one from a 60 fps) but not make 12.5 from 30 (or 60) [and obviously not
  308. make 25 from 12.5...]
  309.  
  310. BatchComp writes video chunks and optionally key frames (key frames permit
  311. the video data to be started from any point in the file, but they take up
  312. space, being uncompressed 16bit per pixel data, so if the file only needs to
  313. play from the start, or the video decompressor does not need key frames they
  314. can be omitted). BatchComp writes all data in the specified destination
  315. directory (which is where the the ARMovie header file is, called "Header")
  316. and the video chunks will be filed separately using the following name for
  317. each chunk:
  318.  
  319.  "Images"+STR$(chunk%DIV77)+"."+RIGHT$("0"+STR$(chunk%MOD77),2)
  320.  
  321. If writing key frames they are filed as:
  322.  
  323.  "Keys"+STR$(chunk%DIV77)+"."+RIGHT$("0"+STR$(chunk%MOD77),2)
  324.  
  325. These data files form part of the input data for the 'Join' program which
  326. is used to make an ARMovie file after the compressor has run.
  327.  
  328. BatchComp may write a log of all the work it has done, this is stored as Log
  329. in the destination, and may write similar information to the screen (the
  330. Acorn compressors do). If the BatchComp process is slow (it is for the Acorn
  331. software compressors), then BatchComp should periodically (e.g. 20 minute
  332. intervals) save enough data so that it can continue in case the computer
  333. stops unexpectedly: (Acorn compressors save this is in three files
  334. "StoppedD", "StoppedC" and "StoppedF" in the destination directory - for
  335. the correct working of !AREncode it is recommended that the files begin
  336. with "Stopped").
  337.  
  338. Similarly, it is recommended that BatchComp be suspendable such that it can
  339. be restarted. Pressing the space bar should be used as the trigger for this
  340. so that your BatchComp behaves that same as other BatchComps. It is expected
  341. that a similar set of Stopped files be used for restarting BatchComp some
  342. time later.
  343.  
  344. It can be convenient for several collections of header/images/keys to be
  345. stored in the same directory: the compressor parameter -index N allows any
  346. number of collections to be stored with names Header/Images/Keys/Log
  347. (default) 1Header/1Images/1Keys/1Log etc. Stopped files are also prefixed by
  348. the index.
  349.  
  350. If a compression program has a BASIC shell (or is written entirely in BASIC)
  351. then there is a common front end library (<ARMovie$Dir>.Tools.CompLib) which
  352. provides much of the mechanics for writing a BatchComp. The Moving Lines and
  353. Moving Blocks compressors use this.
  354.  
  355. The parameters are:
  356.  
  357. -arm2      limit the size of a frame to something that can be decompressed
  358.            by an 8MHz ARM2 machine, if this has any meaning for that
  359.            decompressor.
  360.  
  361. -batch     set batch mode: BatchComp should not attempt to detect the space
  362.            bar being pressed to suspend it. This is to stop command files
  363.            being sucked in a byte at a time each time a detect for space bar
  364.            being pressed was made.
  365.  
  366. -dest b.   set directory for destination (compressed) data: the Header, Images,
  367.            Keys are here. If a full pathname is used for this and the source,
  368.            then the BatchComp program should be able to continue processing
  369.            whatever else is happening (it may be multitasking in a task
  370.            window for example). [aside: if the destination doesn't end in a
  371.            directory separator, then add one!]
  372.  
  373. -dirty     specifies a 'quick and dirty' approach to compression if
  374.            possible. For example, in the MovingLines compressor it tells the
  375.            compressor to use a faster but less accurate method of varying
  376.            the quality to attain the target frame size. Parameter is ignored
  377.            by compressors which can attach no meaning to this hint.
  378.  
  379. -display N causes BatchComp to switch to screen mode N and display the
  380.            images being compressed. Typically the original image would be
  381.            displayed on the bottom right of the screen and the compressed
  382.            image on the bottom left. If the compressed image can't be fitted
  383.            then only the uncompressed image would be displayed. N may be a
  384.            RISC OS 3.5 mode description string. Using this option when
  385.            invoking BatchComp from a TaskWindow is not recommended!
  386.  
  387. -double    assume the decompressor will be using double buffered data
  388.            (default: single) when it plays the movie back: this makes the
  389.            number of bytes available for a frame larger for devices with
  390.            high latency (such as CDROM) and thus improves the quality of the
  391.            movie. The only result of asserting this is to change the text
  392.            printed by the compressor when it calculates the amount of
  393.            memory needed to decompress the movie (which is, of course,
  394.            specific to a codec).
  395.  
  396. -filter    invoke filter or list of filters separated by ';' characters.
  397.            Filters are stored in directory <ARMovie$Dir>.Tools.Filters.
  398.            Filters are applied in the specified order:
  399.  
  400.               -filter TClamp;Median
  401.  
  402.            applies the temporal clamp first, then the spatial median. See
  403.            below for filter machine code interface.
  404.  
  405. -index N   select different Header, Images, Keys, Log combination (default
  406.            is no prefix). Different header files can be used to make
  407.            different movies from the same source - for example with
  408.            different sound tracks or with different frame per second rates.
  409.  
  410. -nokeys    prevents the key frames being written: this results in a smaller
  411.            movie file which can only be started at the beginning (or at
  412.            other "natural" cut points - for example where the movie changes
  413.            from all white to all black). If the key frame data structure was
  414.            written, a movie without keys can still be made if required.
  415.            If keys are not important to the video compression algorithm, then
  416.            this parameter is ignored.
  417.  
  418. -notext    suppresses all textual output
  419.  
  420. -quality N set quality mode and the quality: in the normal mode, BatchComp
  421.            programs adjust the quality to maintain the average frame size at
  422.            the required value. However, this may take time and can produce a
  423.            movie with frames of poor quality. Using -quality will produce a
  424.            movie with a particular quality for all frames, but the frame
  425.            size varies. Quality numbers are higher for poor quality frames,
  426.            lower for frames which are very accurately matched to the source
  427.            frames. Users should make a small test run to find a suitable
  428.            quality value for a particular movie and compression program -
  429.            values for different Decomp<N>.BatchComp for a similar visual
  430.            quality may well be very different (and produce different amounts
  431.            of output). Quality 0 is taken to mean IDENTICAL with the source,
  432.            there is no specified upper limit (users should be referred to
  433.            information on the values for a particular BatchComp).
  434.  
  435. -restart   continue processing using the "Stopped" files. Only -dest,
  436.            -index and -source need be given. It is recommended that the
  437.            StoppedD file be used to store all the other parameters.
  438.            New values for -batch and -display are required.
  439.  
  440. -size N    set frame size to N (may come from a data/latency computation).
  441.            Values in the range 5000 to 10000 are reasonable for playback
  442.            from hard discs.
  443.  
  444. -source f  set name of source file
  445.  
  446. -startat N set initial start point from the source file in centiseconds
  447.            (default zero). (just like -startat when playing a movie).
  448.  
  449. Any not understood parameters should be ignored. Parameter strings may have
  450. got too long for the RISC OS 256 character limit on command strings, so some
  451. of the parameters may be in 'ARMovie$ExtraArgs': if this exists and has a
  452. non-zero length, then it should also be read for input parameters, then set
  453. to a null string. Programmers are encouraged to read the
  454. MovingLine.BatchComp source...
  455.  
  456. Note that it is possible to make 'BatchComp' a directory and embed more
  457. resources within it, the entry BatchComp.!Run being used automatically
  458. by the operating system.
  459.  
  460. The calculations to go from bandwidth/latency to frame size are:
  461.  
  462.   size=((chunktime*double-latency)/double*datarate-soundbytes ANDNOT1023)/fpf
  463.  
  464. where the variables are:
  465.  
  466. chunktime: time for a chunk           (e.g. 2 seconds)
  467. double:    1 for single buffer
  468.            2 for double buffer
  469. latency:   latency time               (e.g. 0.4 seconds)
  470. datarate:  data rate for time base    (e.g. 150*1024 bytes per second)
  471. soundbytes:number of bytes of sound data in a chunk
  472. fpf:       frames per chunk
  473.  
  474. The soundbytes value is calculated from reading all the sound track
  475. information in the header. Chunktime and fpf values are also from the
  476. header.
  477.  
  478. The program should claim as much application workspace (only) as it requires.
  479.  
  480. ARMovie$CompressionStatus is an OS variable that the compressor writes to as
  481. it exits (for whatever reason). It can take the following values:
  482.  
  483.  - does not exist: no error, job successful
  484.  
  485.  - exists and contains SUSPEND: job suspended, new stopped files written
  486.    for continuation later.
  487.  
  488.  - else: contains textual error (reason why BatchComp stopped). The compression
  489.    job has been aborted 'due to unforeseen circumstances'. If stopped files
  490.    are present it can be continued (the files may be historical!)
  491.  
  492. The value must be read and remembered by the calling program on the exit from
  493. BatchComp - it may be reset by any other compression tasks which are floating
  494. around the machine when the next task swap occurs.
  495.  
  496. Filters
  497. -------
  498.  
  499. Image processing filters can make a big difference to the quality of compressed
  500. scenes. If dithering has been used, however, the filters may dramatically
  501. reduce the colour range. It is also possible to use the filter code in other
  502. programs. The interface is as follows:
  503.  
  504. Callers load the filter code at a quad word aligned address in memory. The init
  505. routine is called. Then the filter routine is called as necessary.
  506.  
  507. First word: init entry point
  508. (byte offset 0)
  509.  
  510.  Purpose: allows filter to initialise any values it needs (these are stored
  511.           inside the filter's code space or allocated by the init routine).
  512.  
  513.  On entry:
  514.    r0 - source x size of movie
  515.    r1 - source y size of movie
  516.    r2 - colour space of movie: 0: RGB 5,5,5
  517.                                1: YUV 5,5,5
  518.                                2: Y 8
  519.                                3: RGB 8,8,8
  520.                                4: YUV 8,8,8
  521.    r3..r12 - undefined: scratch
  522.    r13 - stack
  523.    r14 - return address
  524.    processor mode: USR
  525.  On exit
  526.    r0-r12 - may be corrupted
  527.    r13 - same as on entry
  528.    flags - V set signals error: r0 points to an error block
  529.  
  530. Second word: filter one frame
  531.  
  532.  Purpose: apply the filter and produce one filtered frame
  533.  
  534.  On entry:
  535.    r0 - buffer to be filtered (word aligned)
  536.    r1 - previous output pointer (allows temporal filtering from previous frame)
  537.         (0 if no previous frame available)
  538.    r2 - result pointer - save output pixels here (word aligned)
  539.    r3..r12 - scratch
  540.    r13 - stack
  541.    r14 - return address
  542.    processor mode: USR *or* SVC, interrupts ENABLED (usually)
  543.    flags - irrelevant
  544.  On exit
  545.    r0..r12 - irrelevant
  546.    r13 - must be same value as on entry
  547.    r14 - irrelevant
  548.    processor mode: same as called mode
  549.    flags - irrelevant
  550.  
  551.  Pixels are stored as Words!!! (well, the bottom 15 bits of one, anyway)
  552.